package tool

import com.softwaremill.quicklens._
import dao.{AccountDao, MemberDao, SpecialMemberDao, UserDao}
import implicits.Implicits._
import play.api.libs.json.{JsValue, Json}
import play.api.mvc.RequestHeader
import tool.Pojo.{CSampleInfo, ChangePasswordData, MyException}
import utils.Utils

import java.io.File
import scala.collection.immutable.SeqMap
import scala.concurrent.ExecutionContext.Implicits.global
import models.Tables._

import scala.concurrent.Future
import scala.util.Random
import argonaut._
import Argonaut._
import ArgonautShapeless._

/**
 * Created by yz on 19/8/2021
 */
trait ProjectTool {

  def parseConfigInfo(configInfo: String) = {
    val lines = configInfo.toLines.map(_.trim)
    val newLinesT = lines.dropWhile(x => !x.trim.startsWith("[")).foldLeft((List[String](), false)) { (tmpX, y) =>
      val (x, canAppend) = tmpX
      if (y.startsWith("[")) {
        (x :+ y, false)
      } else if (y.contains("=")) {
        (x :+ y, true)
      } else if (canAppend) {
        (x.init :+ (x.last + y), canAppend)
      } else {
        tmpX
      }
    }
    newLinesT._1.foldLeft(SeqMap[String, SeqMap[String, List[String]]]()) { (map, y) =>
      if (y.startsWith("[")) {
        val kitName = y.drop(1).dropRight(1)
        map + (kitName -> SeqMap.empty)
      } else {
        val (lastKey, lastV) = map.last
        val values = y.mySplit("=").take(2).map(_.trim)
        if (values.size < 2) {
          map
        } else {
          val newVs = values.last.mySplit(";").map(_.trim)
          val t = (values.head, newVs)
          map.updated(lastKey, lastV + t)
        }
      }
    }.map { case (kitName, configMap) =>
      val newConfigMap = configMap.filter { case (k, vs) =>
        vs.nonEmpty
      }
      (kitName, newConfigMap)
    }.filter { case (kitName, configMap) =>
      configMap.nonEmpty
    }
  }

  def parseConfig(config: String) = {
    val lines = config.toLines.map(_.trim)
    val newLines = lines.dropWhile(x => !x.trim.contains("=")).foldLeft(List[String]()) { (x, y) =>
      if (y.contains("=")) {
        x :+ y
      } else {
        x.init :+ (x.last + y)
      }
    }
    newLines.foldLeft(SeqMap[String, List[String]]()) { (map, y) =>
      val values = y.mySplit("=").take(2).map(_.trim)
      if (values.size < 2) {
        map
      } else {
        val newVs = values.last.mySplit(";").map(_.trim)
        val t = (values.head, newVs)
        map + t
      }
    }.filter { case (k, vs) =>
      vs.nonEmpty
    }
  }

  def parseRowFilterConfigInfo(configInfo: String) = {
    val lines = configInfo.toLines.map(_.trim)
    val newLinesT = lines.dropWhile(x => !x.trim.startsWith("[")).foldLeft((List[String](), false)) { (tmpX, y) =>
      val (x, canAppend) = tmpX
      if (y.startsWith("[")) {
        (x :+ y, false)
      } else if (y.contains("=")) {
        (x :+ y, true)
      } else if (canAppend) {
        (x.init :+ (x.last + y), canAppend)
      } else {
        tmpX
      }
    }
    newLinesT._1.foldLeft(SeqMap[String, List[JsValue]]()) { (map, y) =>
      if (y.startsWith("[")) {
        val kitName = y.drop(1).dropRight(1)
        map + (kitName -> List.empty)
      } else {
        val (lastKey, lastV) = map.last
        val values = y.mySplit("=").take(2).map(_.trim)
        if (values.size < 2) {
          map
        } else {
          val newV = filterStr2Json(values.head.trim, values.last.trim)
          map.updated(lastKey, lastV :+ newV)
        }
      }
    }.filter { case (kitName, configJsons) =>
      configJsons.nonEmpty
    }
  }

  def dbFmt(v: String) = {
    v match {
      case "-Inf" => Double.MinValue
      case "Inf" => Double.MaxValue
      case _ =>
        if (!v.isDouble) {
          throw new MyException(s"${v}不为Double类型")
        }
        v.toDouble
    }
  }

  def filterStr2Json(columnName: String, filterStr: String) = {
    if (filterStr.matches("^\\(.*\\)$")) {
      val values = filterStr.replaceAll("^\\(", "").
        replaceAll("\\)$", "").mySplit(",")
      if (values.size < 2) {
        throw new MyException(s"${columnName}没有正确的配置数字范围！")
      }
      val minV = values.head
      val maxV = values.last
      try {
        Json.obj(
          "kind" -> "num",
          "name" -> columnName,
          "min" -> dbFmt(minV),
          "max" -> dbFmt(maxV),
        )
      } catch {
        case e: Exception =>
          throw new MyException(s"${columnName}配置格式不正确(${e.getMessage})！")
      }
    } else {
      val values = filterStr.mySplit(",")
      Json.obj(
        "name" -> columnName,
        "kind" -> "checkbox",
        "value" -> values,
      )
    }
  }

  def parseRowFilterConfig(config: String) = {
    val lines = config.toLines.map(_.trim)
    val newLines = lines.dropWhile(x => !x.trim.contains("=")).foldLeft(List[String]()) { (x, y) =>
      if (y.contains("=")) {
        x :+ y
      } else {
        x.init :+ (x.last + y)
      }
    }
    newLines.foldLeft(List[JsValue]()) { (jsons, y) =>
      val values = y.mySplit("=").take(2).map(_.trim)
      if (values.size < 2) {
        jsons
      } else {
        val newV = filterStr2Json(values.head.trim, values.last.trim)
        jsons :+ newV
      }
    }
  }

  def deleteKitName(kitMap: SeqMap[String, List[String]], deleteKitInfos: List[(String, String)]): SeqMap[String, List[String]] = {
    deleteKitInfos match {
      case Nil => kitMap
      case x :: xs =>
        val (tableName, kitName) = x
        val newKitMap = kitMap.updatedWith(tableName) { kitNamesOp =>
          kitNamesOp.map { kitNames =>
            kitNames.filter(_ != kitName)
          }
        }.filter { case (tableName, kitNames) =>
          kitNames.nonEmpty
        }
        deleteKitName(newKitMap, xs)
    }
  }

  def deleteRowFilter(map: SeqMap[String, String], deleteInfos: List[(String, String)]): SeqMap[String, String] = {
    deleteInfos match {
      case Nil => map
      case x :: xs =>
        val (tableName, name) = x
        val newKitMap = map.updatedWith(tableName) { kitNameOp =>
          kitNameOp.filter { kitName =>
            kitName != name
          }
        }
        deleteRowFilter(newKitMap, xs)
    }
  }

  def updatePassword(account: String, data: ChangePasswordData)(implicit accountDao: AccountDao, memberDao: MemberDao,
                                                                specialMemberDao: SpecialMemberDao) = {
    val accountF = accountDao.selectById1.flatMap { x =>
      if (account == account && data.password == x.password) {
        val row = AccountRow(x.id, x.account, data.newpassword)
        accountDao.update(row).map { y =>
          true
        }
      } else Future {
        false
      }
    }
    val memberF = memberDao.select(account, password = data.password).flatMap { xOp =>
      xOp.map { x =>
        val newRow = x.copy(password = data.newpassword)
        memberDao.update(newRow).map { y =>
          true
        }
      }.getOrElse {
        Future {
          false
        }
      }
    }
    val specialMemberF = specialMemberDao.select(account, password = data.password).flatMap { xOp =>
      xOp.map { x =>
        val newRow = x.copy(password = data.newpassword)
        specialMemberDao.update(newRow).map { y =>
          true
        }
      }.getOrElse {
        Future {
          false
        }
      }
    }
    Future.sequence(List(accountF, memberF,specialMemberF)).map { bs =>
      bs.reduceLeft(_ || _)
    }

  }

  def productValidCode = {
    ("0" * 11).map { i =>
      (Random.nextInt(10) + '0').toChar
    }
  }

  def getData(content: String) = {
    content.decodeOption[CSampleInfo].get
  }


}
